home *** CD-ROM | disk | FTP | other *** search
- /***** BEGIN LICENSE BLOCK *****
-
- FlashGot - a Firefox extension for external download managers integration
- Copyright (C) 2004-2009 Giorgio Maone - g.maone@informaction.com
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
- ***** END LICENSE BLOCK *****/
-
- var MediaSniffer = {
-
- QueryInterface: xpcom_generateQI([
- CI.nsIObserver,
- CI.nsISupportsWeakReference,
- CI.nsISupports,
- CI.nsIWebProgressListener
- ]),
-
-
- debug: false,
- // http-on-examine-response Observer
-
- mimeService: CC['@mozilla.org/uriloader/external-helper-app-service;1']
- .getService(CI.nsIMIMEService),
- mediaTypesRx: /\b(?:audio|video|smil)\b/i,
- mediaMap: {
- "asx": "video/x-ms-asx", // fake, see "media" processor
- "flv": "video/flv", // flv is not mapped by MimeService
- "f4v": "video/mp4",
- "f4a": "video/mp4",
- "f4b": "video/mp4",
- "f4p": "video/mp4",
- "mp3": "audio/mp3", // MimeService chokes on this
- "mp4": "video/mp4" // just to be sure :)
- },
- get inverseMediaMap() {
- var m = {};
- for (var p in this.mediaMap) m[this.mediaMap[p]] = p;
- delete this.inverseMediaMap;
- return this.inverseMediaMap = m;
- },
-
- sniffType: function(channel, forcedContentType) {
- var path;
- if (channel instanceof CI.nsIHttpChannel) {
- try {
- path = channel.getResponseHeader("content-disposition").match(/; filename="([^"]+)/i)[1];
- } catch(e) {}
- }
- if (!path) path = channel.URI.path;
- path = path.replace(/#[\s\S]*/, '');
- if (path.length > 1024) path = path.substring(0, 1024);
- const extFinder = /([^"\/]+\.(\w{2,5}))(?=[\?&]|$)/g;
- extFinder.lastIndex = 0;
- var m, ext, contentType, ms;
- while((m = extFinder.exec(path))) {
- ext = m[2];
- if ((contentType = this.mediaMap[ext])) break;
- try {
- contentType = this.mimeService.getTypeFromExtension(ext);
- if (this.mediaTypesRx.test(contentType)) break;
- } catch(e) {}
- }
-
- var fname;
- if (forcedContentType && !(forcedContentType == "video/x-ms-asf" && contentType == "video/x-ms-asx")) {
- var fname = m && m[1];
- if (!fname) {
- fname = (channel.URI instanceof CI.nsIURL) && channel.URI.fileName || path.replace(/.*\//g, '');
- try {
- fname += "." + (this.inverseMediaMap[forcedContentType] || this.mimeService.getPrimaryExtension(forcedContentType, ''));
- } catch(ex) {}
- }
- return { fname: fname, contentType: forcedContentType };
- }
-
- return m && { fname: m[1], contentType: contentType };
- },
-
-
-
- observe: function(channel, topic, data) {
- if (channel instanceof CI.nsIChannel) {
- try {
- var contentType = channel.contentType;
- if (!contentType || /\b(?:x?html|image|css|javascript|shockwave)\b/i.test(contentType)) return;
-
- if (this.debug) dump("Examining " + channel.URI.spec + " (" + contentType + ")\n");
-
- var typeInfo = null;
- if (this.mediaTypesRx.test(contentType) || (typeInfo = this.sniffType(channel))) {
-
- var win = (DOM.findChannelWindow(channel) || DOM.mostRecentBrowserWindow.content).top;
-
- if (this.debug) dump("Media Window: " + win + " - " + win.location.href + " -- " + contentType + "\n");
- var media = win._flashgotMedia || (win._flashgotMedia = []);
- var url = channel.URI.spec;
- var map = media._map || (media._map = {});
-
- if (!(url in map)) {
-
- contentType = contentType.replace(/;.*/); // ignore trailing extras, e.g. charset
-
- if (/\bx-ms-asf\b/.test(contentType)) {
- try {
- if (channel.contentLength && channel.contentLength < 2048) contentType = "video/x-ms-asx";
- } catch(e) {}
- try {
- if (channel.contentCharset && channel.contentLength < 16384) contentType = "video/x-ms-asx";
- } catch(e) {}
- }
-
- // asf content type can also refer to an asx, we need to check the file name to decide
- if (!typeInfo) {
- typeInfo = this.sniffType(channel, contentType)
- }
-
- contentType = typeInfo.contentType;
-
- var contentLength = -1;
- try {
- contentLength = channel.contentLength;
- } catch (e) {}
-
- var tip = url.match(/[^\/]*$/)[0] || '';
- if (tip) {
- tip = contentType + ": " + tip;
- if (tip.length > 60) {
- tip = tip.substring(0, 29) + "..." + tip.slice(-28);
- }
- } else tip = contentType;
-
-
- // Youtube channel hack
- var doc = win.document;
- var node = doc.getElementById("playnav-curvideo-title");
-
- var title = (node && node.textContent || win.document.title).replace(/^\s+|\s+$/, '') || '';
- const unicode = fg.getPref("media.unicode") && /^UTF.?8$/i.test(win.document.characterSet);
- if (title) {
- // remove site name from title
- title = title.replace(new RegExp("\\b(?:" +
- (win.location.host || '').split(".").filter(function(s) { return s }).join("|") + ")\\b", 'ig'), '')
- .replace(/https?:\/{2}/gi, '').replace(unicode ? /^[^\w\u0080-\uffff]*(.*?)[^\w\u0080-\uffff]*$/g : /^\W*(.*?)\W*$/g, '$1').replace(unicode ? /[\u0000-\u0020]+/g : /\W+/g, '_')
- }
-
- var fname = title && fg.getPref("media.guessName", true) && (title + "_" + typeInfo.fname)
- .replace(unicode ? /[^\w\.\u0080-\uffff]+/g : /[^\w\.]+/g, '_').replace(/_(?:get_video|videoplayback)\b/, '')
- || '';
-
- var redirect;
- var host = (channel.originalURI || channel.URI).host;
- if (host) {
- host = host.replace(/\./g, '_');
- while(host && (redirect = fg.getPref("media.redirect." + host, -1)) == -1) {
- host = host.replace(/.*?(?:_|$)/, '');
- }
- }
- if (redirect == -1) redirect = fg.getPref("media.redirect", 0); // 0 - no redirect, 1 redirect, 2 include both initial and final url
- if (redirect == 0) url = channel.originalURI && channel.originalURI.spec || url;
-
-
- var size = contentLength < 0 ? "???KB"
- : contentLength < 1024 ? (contentLength + "B")
- : contentLength < 1048576 ? (Math.round(contentLength / 1024) + "KB")
- : (Math.round(contentLength / 1048576)) + "MB";
-
-
- var label = (fname || tip) + " (" + size + ")";
- var description = title + " (" + contentType + ", " + size + ")";
- tip += " (" + size + ")";
-
- while(url) {
- media.push (map[url] = {
- href: (fname && fg.getPref("media.forceNameHack", true) && url.indexOf("#") == -1) ? url + "#/" + encodeURIComponent(fname) : url,
- referrer: (channel instanceof CI.nsIHttpChannel) && channel.referrer && channel.referrer.spec,
- description: title + " (" + contentType + ")",
- contentType: contentType,
- contentLength: contentLength,
- label: label,
- tip: tip,
- fname: fname
- });
-
- url = redirect == 2 && (!channel.originalURI || channel.originalURI.spec == url ? null : channel.originalURI.spec);
- }
- }
-
- var bw = DOM.mostRecentBrowserWindow;
- if (bw && bw.gFlashGot) bw.gFlashGot.updateMediaUI();
-
- if (this.debug) dump(win._flashgotMedia && win._flashgotMedia.toSource() + "\n");
- }
- } catch(e) {
- var msg = topic + " " + e.toString();
- if (channel) {
- msg += " -- " + channel.URI.spec;
- try {
- msg += ", " + channel.contentType;
- } catch(e1) {}
- }
- if (this.debug) dump(msg + "\n");
- }
- }
- },
-
- onStateChange: function(wp, channel, stateFlag, status) {
- // here we wait STATE_STOP of cached channels
- if ((stateFlag & 16) && (channel instanceof CI.nsICachingChannel))
- this.observe(channel, "http-cached-stop", null);
- }
- /*
- ,
- onLocationChange: function(wp, req, location) {}
- ,
- onLinkIconAvailable: function() {},
- onStatusChange: function() {},
- onSecurityChange: function() {},
- onProgressChange: function() {}
- */
- };